﻿#include "FITKAbaqusAdaptorMaterialHyperelastic.h"
#include "InpKeyLineSpliter.h"

#include "FITKAbaqusINPReader.h"
#include "FITKAbaqusINPWriter.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMaterial.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMaterialHyperElastic.h"

namespace IO
{
    QString FITKAbaqusAdaptorMaterialHyperelastic::getAdaptorClass()
    {
        return "IO::FITKAbaqusAdaptorMaterialHyperelastic";
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::adaptR()
    {
        
        _materialData = dynamic_cast<Interface::FITKAbaMaterial*>(_dataObj);
        if (!_materialData || !_reader) return false;

        //回退一行 处理关键字信息 校验
        _reader->backLine();
        QString line = _reader->readLine();
        if (!(line.toLower().startsWith("*hyperelastic") || line.toLower().startsWith("*anisotropic hyperelastic"))) return false;
        //设置类型为超弹性
        Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType materialType =
            Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Hyperelastic;
        //创建超弹性行为
        bool create = _materialData->addMaterialBehavior(materialType);
        if (!create)return false;
       //处理数据
        InpKeyLineSpliter s(line, _reader);
        QString sH = s.getHeader().toLower();
        bool readOK = false;
        //各向同性
        if (sH == "hyperelastic")
        {
            readOK = this->readIsotropicHyperelastic();
        }
        //各向异性
        else if (sH == "anisotropic hyperelastic")
        {
            readOK = this->readAnisotropicHyperelastic();
        }
        //读取失败移除超弹性行为
        if (!readOK)
            _materialData->removeMaterialBehavior(materialType);
        return readOK;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::adaptW()
    {
        _materialData = dynamic_cast<Interface::FITKAbaMaterial*>(_dataObj);
        if (!_materialData || !_writer) return false;
        //设置类型为超弹性
        Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType materialType =
            Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Hyperelastic;
        //获取超弹性行为
        bool writeOK = false;
        Interface::FITKAbaMaterialHyperElastic* hyperelastic = dynamic_cast<Interface::FITKAbaMaterialHyperElastic*>(_materialData->getMaterialBehavior(materialType));
        //材料为空则返回
        if (!hyperelastic) return true;
        if (hyperelastic->getMaterialType() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticMaterialType::HyereAnisotropic)
            writeOK = this->writeAnisotropicHyperelastic();
        else if (hyperelastic->getMaterialType() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticMaterialType::HyereIsotropic)
            writeOK = this->writeIsotropicHyperelastic();

        return writeOK;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::readIsotropicHyperelastic()
    {
        if (!_materialData)return false;
        //获取超弹性行为
        Interface::FITKAbaMaterialHyperElastic* hyperelastic = dynamic_cast<Interface::FITKAbaMaterialHyperElastic*>
            (_materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Hyperelastic));
        if (!hyperelastic)return false;
        //设置各向同性
        hyperelastic->setMaterialType(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticMaterialType::HyereIsotropic);
        //回退一行 处理关键字信息 校验
        _reader->backLine();
        QString line = _reader->readLine();
        //处理数据
        InpKeyLineSpliter s(line, _reader);
        bool readOK = false;
        if (s.hasKey("arruda-boyce"))
        {
            readOK = this->readIsotropicHyperelasticArruda_Boyce();
        }
        else if (s.hasKey("marlow"))
        {

        }
        else if (s.hasKey("mooney-rivlin"))
        {
            readOK = this->readIsotropicHyperelasticMooney_Rivlin();
        }
        else if (s.hasKey("neo hooke"))
        {

        }
        else if (s.hasKey("ogden"))
        {

        }
        else if (s.hasKey("polynomial"))
        {

        }
        else if (s.hasKey("reduced polynomial"))
        {

        }
        else if (s.hasKey("user"))
        {

        }
        else if (s.hasKey("van der waals"))
        {

        }
        else if (s.hasKey("yeoh"))
        {

        }
        return readOK;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::readIsotropicHyperelasticArruda_Boyce()
    {
        if (!_materialData)return false;
        //获取超弹性行为
        Interface::FITKAbaMaterialHyperElastic* hyperelastic = dynamic_cast<Interface::FITKAbaMaterialHyperElastic*>
            (_materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Hyperelastic));
        if (!hyperelastic)return false;
        //设置应变势能Arruda_Boyce
        hyperelastic->setIsoStrainEnergyPotential(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::ArrudaBoyce);
        //回退一行 处理关键字信息 校验
        _reader->backLine();
        QString line = _reader->readLine();
        //处理数据
        InpKeyLineSpliter s(line, _reader);
        bool ok = false;
        //读取输入源
        if (s.hasKey("test data input"))
            hyperelastic->setIsoInputSource(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::TestData);
        else
            hyperelastic->setIsoInputSource(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::Coeffcients);
        //读取模量状态
        QString moduli = s["moduli"].toUpper();
        if (moduli == "LONG TERM" || moduli.isEmpty())
            hyperelastic->setIsoModuliTimeScale(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsoModuliTimeScale::LongTerm);
        else if (moduli == "INSTANTANEOUS")
            hyperelastic->setIsoModuliTimeScale(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsoModuliTimeScale::Instantaneous);
        //用于定义体积响应的数据
        if (s.hasKey("poisson"))
        {//泊松比
            double poisson = s["poisson"].toDouble(&ok);
            if (!ok)return false;
        }
        else
        {//体积试验参数

        }
        //使用与温度相关的数据-->无影响，这里设置成false
        hyperelastic->setUseTemperatureDependentData(false);
        //读取试验参数
        if (hyperelastic->getIsoInputSource() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::TestData)
        {
            ok = this->readIsotropicHyperelasticTestData();
            if (!ok)return false;
        }
        //读取系数数据
        else if (hyperelastic->getIsoInputSource() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::Coeffcients)
        {
            for (int i = 0; !_reader->atEnd(); ++i)
            {
                line = _reader->readLine();
                if (line.startsWith("*"))break;
                hyperelastic->setIsoMooneyRivlinDataRows(i + 1);
                QStringList str;
                if (!line.trimmed().isEmpty())
                    str = line.trimmed().split(',');
            }
        }
        //读取滞后作用

        return true;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::readIsotropicHyperelasticMooney_Rivlin()
    {
        if (!_materialData)return false;
        //获取超弹性行为
        Interface::FITKAbaMaterialHyperElastic* hyperelastic = dynamic_cast<Interface::FITKAbaMaterialHyperElastic*>
            (_materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Hyperelastic));
        if (!hyperelastic)return false;
        //设置应变势能Arruda_Boyce
        hyperelastic->setIsoStrainEnergyPotential(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::MooneyRivlin);
        //回退一行 处理关键字信息 校验
        _reader->backLine();
        QString line = _reader->readLine();
        //处理数据
        InpKeyLineSpliter s(line, _reader);
        bool ok = false;
        //读取输入源
        if (s.hasKey("test data input"))
            hyperelastic->setIsoInputSource(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::TestData);
        else
            hyperelastic->setIsoInputSource(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::Coeffcients);
        //读取模量状态
        QString moduli = s["moduli"].toUpper();
        if (moduli == "LONG TERM" || moduli.isEmpty())
            hyperelastic->setIsoModuliTimeScale(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsoModuliTimeScale::LongTerm);
        else if (moduli == "INSTANTANEOUS")
            hyperelastic->setIsoModuliTimeScale(Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsoModuliTimeScale::Instantaneous);
        //用于定义体积响应的数据
        if (s.hasKey("poisson"))
        {//泊松比
            double poisson = s["poisson"].toDouble(&ok);
            if (!ok)return false;
        }
        else
        {//体积试验参数

        }
        //读取试验参数
        if (hyperelastic->getIsoInputSource() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::TestData)
        {
            //使用与温度相关的数据-->无影响，这里设置成false
            hyperelastic->setUseTemperatureDependentData(false);
            //试验数据
            ok = this->readIsotropicHyperelasticTestData();
            if (!ok)return false;
        }
        //读取系数数据
        else if (hyperelastic->getIsoInputSource() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::Coeffcients)
        {
            for (int i = 0; !_reader->atEnd(); ++i)
            {
                line = _reader->readLine().trimmed();
                if (line.startsWith("*"))break;
                hyperelastic->setIsoMooneyRivlinDataRows(i + 1);
                if (line.endsWith(','))line.chop(1);
                QStringList str;
                if (!line.trimmed().isEmpty())
                    str = line.trimmed().split(',');
                if (str.size() >= 4)
                    hyperelastic->setUseTemperatureDependentData(true);
                for (int j = 0; j < str.size(); ++j)
                {
                    double v = str.at(j).trimmed().toDouble(&ok);
                    if (!ok)return false;
                    if (j == 0)
                        hyperelastic->setIsoMooneyRivlinC10(v, i);
                    else if (j == 1)
                        hyperelastic->setIsoMooneyRivlinC01(v, i);
                    else if (j == 2)
                        hyperelastic->setIsoMooneyRivlinD1(v, i);
                    else if (j == 3)
                        hyperelastic->setIosMooneyRivlinTemperature(v, i);
                }
            }
        }
        //读取滞后作用

        return true;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::readIsotropicHyperelasticTestData()
    {
        return false;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::readAnisotropicHyperelastic()
    {
        return false;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::writeIsotropicHyperelastic()
    {
        if (!_materialData || !_writer)return false;
        //获取超弹性行为
        Interface::FITKAbaMaterialHyperElastic* hyperelastic = dynamic_cast<Interface::FITKAbaMaterialHyperElastic*>
            (_materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Hyperelastic));
        //获取应变势能
        bool writeOK = false;
        Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential type = hyperelastic->getIsoStrainEnergyPotential();
        if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::ArrudaBoyce)
        {
            writeOK = this->writeIsotropicHyperelasticArruda_Boyce();
        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::Marlow)
        {

        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::MooneyRivlin)
        {
            writeOK = this->writeIsotropicHyperelasticMooney_Rivlin();
        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::NeoHooke)
        {

        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::Ogden)
        {

        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::Polynomial)
        {

        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::ReducePolynomial)
        {

        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::UsrDefined)
        {

        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::VanderWaals)
        {

        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::Yeoh)
        {

        }
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicStrainEnergyPotential::Unknown)
        {
            _writer->consoleMessage(3, QString("Write Hyperelastic Material Error, A strain energy potential other than Unknown must be selected for hyperelastic material ."));
            return false;
        }
        return writeOK;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::writeIsotropicHyperelasticArruda_Boyce()
    {
        if (!_materialData || !_writer)return false;
        //获取超弹性行为
        Interface::FITKAbaMaterialHyperElastic* hyperelastic = dynamic_cast<Interface::FITKAbaMaterialHyperElastic*>
            (_materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Hyperelastic));
        if (!hyperelastic)return false;
        return false;
    }
    
    bool FITKAbaqusAdaptorMaterialHyperelastic::writeIsotropicHyperelasticMooney_Rivlin()
    {
        if (!_materialData || !_writer)return false;
        //获取超弹性行为
        Interface::FITKAbaMaterialHyperElastic* hyperelastic = dynamic_cast<Interface::FITKAbaMaterialHyperElastic*>
            (_materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Hyperelastic));
        if (!hyperelastic)return false;
        QTextStream* stream = _writer->getStream();
        QString lineOne = "*Hyperelastic, mooney-rivlin";
        //获取输入源
        if (hyperelastic->getIsoInputSource() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsotropicInputSource::TestData)
        {
            lineOne += ", test data input";
            if (hyperelastic->getIsoModuliTimeScale() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsoModuliTimeScale::Instantaneous)
                lineOne += ", moduli=INSTANTANEOUS";
            *stream << lineOne << endl;
        }
        else
        {
            if (hyperelastic->getIsoModuliTimeScale() == Interface::FITKAbaMaterialBehaviorEnum::HyperelasticIsoModuliTimeScale::Instantaneous)
                lineOne += ", moduli=INSTANTANEOUS";
            *stream << lineOne << endl;
            //写出系数数据
            bool isTemperature = hyperelastic->getUseTemperatureDependentData();
            int countRow = hyperelastic->getIsoMooneyRivlinDataRows();
            for (int i = 0; i < countRow; ++i)
            {
                if (isTemperature)
                    *stream << QString("%1, %2, %3, %4").arg(_writer->double2String(hyperelastic->getIsoMooneyRivlinC10(i), 7, 8)).arg(_writer->double2String(hyperelastic->getIsoMooneyRivlinC01(i), 7, 8))
                        .arg(_writer->double2String(hyperelastic->getIsoMooneyRivlinD1(i), 7, 8)).arg(_writer->double2String(hyperelastic->getIsoMooneyRivlinTemperature(i), 7, 8)) << endl;
                else
                    *stream << QString("%1, %2, %3").arg(_writer->double2String(hyperelastic->getIsoMooneyRivlinC10(i), 7, 8)).arg(_writer->double2String(hyperelastic->getIsoMooneyRivlinC01(i), 7, 8))
                    .arg(_writer->double2String(hyperelastic->getIsoMooneyRivlinD1(i), 7, 8)) << endl;
                        
            }
        }
        return true;
    }

    bool FITKAbaqusAdaptorMaterialHyperelastic::writeAnisotropicHyperelastic()
    {
        return false;
    }
}
